package com.mdc.mansion.core.common.util;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.mdc.mansion.common.Md5RsaUtils;
import com.mdc.mansion.common.exception.BusinessException;
import com.mdc.mansion.common.util.HttpUtil;
import com.mdc.mansion.common.util.StringUtils;
import com.mdc.mansion.core.common.config.CoreGlobal;
import com.mdc.mansion.core.modules.pay.dto.AltoPayCallResult;
import com.mdc.mansion.core.modules.pay.dto.AltoPayQryResult;
import com.mdc.mansion.core.modules.pay.dto.AltoPayResult;
import com.mdc.mansion.core.modules.pay.dto.AltoRefundCallResult;
import com.mdc.mansion.core.modules.pay.dto.AltoRefundQryResult;
import com.mdc.mansion.core.modules.pay.dto.AltoResult;
import com.mdc.mansion.core.modules.pay.mo.AltoPayMo;
import com.mdc.mansion.core.modules.pay.mo.AltoPayQryMo;
import com.mdc.mansion.core.modules.pay.mo.AltoRefundMo;
import com.mdc.mansion.core.modules.pay.mo.AltoRefundQryMo;
import com.mdc.mansion.dataaccess.modules.pay.entity.RestaurantPayCfg;

public class AltoPayUtils {
	
	private static Logger log = LoggerFactory.getLogger(AltoPayUtils.class);
	
	private static String base_uri = CoreGlobal.getConfig("base_uri");
	
	private static String pay_uri = base_uri + CoreGlobal.getConfig("pay_uri");
	
	private static String refund_uri = base_uri + CoreGlobal.getConfig("refund_uri");
	
	private static String pay_qry_uri = base_uri + CoreGlobal.getConfig("pay_qry_uri");
	
	private static String refund_qry_uri = base_uri + CoreGlobal.getConfig("refund_qry_uri");
	
//	private static final String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJvb3wm1Gt8wP0fY1sz9QCyVL7k6Nw/zF7jYY0anslunGoHp1WiFPK+sat2HOZQfly42nkYsbF7VxmLmCY9VLmTqL/L3I7lUt63X1KaXfjCzIYOOmW1xjwaoprYzZOEVUjGULF2Pc4Z5vIR6OuF4zl05CPElcP7QEhrRUC/lzCjxAgMBAAECgYB/Jt9M8h0cHCZkHPkQf0NNm+A1QtMNBgtCV/aV+9W8hBVSC0x5WslpoEYGuH025JbXsuNo6HD45XpV0MnXz2xqzcUXNJ5EYXgFSpX4OCm97kmTJRYw0Dzg4VMov7v4T0EBZbQXeGl2jaTJ0usZKzuQKzDJk2bB+Jd2w5xRLdtBqQJBAMzYxwtyL1BGtM30Z6Xa4KqVG/quzz0iA8TPh37560T9NfvYx9FuXkxRNUCM1P5iEiReAcxM6rbB2C5CDRB40UcCQQDCx3KVrsupz3eHBWDhmRgqc1PKTYL8u3Q5HcIu5z1aAJ0Qrq/kdFdh94HdlNMdhWBMRaJr/q1NPP8BO1T0RhAHAkAZ7jcEE+g5WTn5+D5GmHZoIYfxK7/AFVY0y7BzOl+10/fJcZ+Zu0bkkkMTcMBlkzSItf20RuhPSip7cJEGzMRxAkBNOca0khktupQpdHh0+b4bFp6iFxlYGvp5qtLSxdwNUzDy7E/QxE/hB8D1mYwaqEcF9pXvO4p6lTSFyIBmWWEBAkBobn+9vCbUgdvvkbV62ivqI0SRPk9yLnxZ5XVhfTXfslDfBPVJZgijmiybZylR/b06wbsn2SATalgqPXF5mCki";
//
//	private static final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK3NXYvcA33nraQQj4ahu+cp7aoiLQTgu0oZv4gdeGD7YsHIQsyMVg3s/cZxMiJaoCJzE1CXpjZ9tLdZr9jM/Zz11zzu1fQTiRP6ZZv2enMCMA0CaaI5AcHJkZ5f+91DxMpAopuRCnftkgOdnNNsx3fm15nRWWMiY75VkW4eTrwwIDAQAB";
	
//	private static String mchId = "100663";
	
	private static final String pay_call_uri = CoreGlobal.getConfig("pay_call_back");
	
	private static final String refund_call_uri = CoreGlobal.getConfig("refund_call_back");
	
	private static String currency = "IDR";
	
	private static String trade_type = "QR_CODE";
	
	private static String encode = "UTF-8";
	
	private static final String result_code="0";
	
	
	/**
	 * 订单支付工作
	 */
	public static AltoResult orderPay(AltoPayMo payMo, RestaurantPayCfg payCfg) throws Exception {
		verfiyPay(payMo);
		payMo.setCurrency(currency);
		payMo.setTrade_type(trade_type);
		payMo.setNotify_url(pay_call_uri);
		String cipher = DataEncrypt(JSONObject.toJSONString(payMo),payCfg.getPrivateKey());
		Map<String,String> parmMap = new HashMap<String,String>();
		parmMap.put("sign_type","RSA");
		parmMap.put("sign",cipher);
		parmMap.put("data",JSONObject.toJSONString(payMo));
		log.error(JSONObject.toJSONString(payMo));
		log.error(pay_uri);
		String result = HttpUtil.doPost(pay_uri,parmMap);
		AltoResult data = JSONObject.parseObject(result,AltoResult.class);
		if(!result_code.equals(data.getCode()))
		{
			throw new BusinessException(data.getErr());
		}
		if(!data.Verify(data,payCfg.getPublicKey(),encode)){
			log.error("支付调用返回验证失败!");
		}
		data.setResult(JSONObject.parseObject(data.getData(),AltoPayResult.class));
		return data;
	}
	
	private static String DataEncrypt(String dataDtr, String privateKey) throws Exception {
		return Md5RsaUtils.sign(dataDtr, privateKey,encode);
	}
	
	private static void verfiyPay(AltoPayMo payMo) {
		checkAloneField(payMo.getMch_id(),"商户编号");
		checkAloneField(payMo.getOut_trade_no(),"商户订单号");
		checkAloneField(payMo.getSubject(),"订单标题");
		checkAloneNumField(new BigDecimal(payMo.getAmount()),"支付金额");
	}
	
	private static void checkAloneNumField(BigDecimal amount, String fieldName) {
		if(amount.compareTo(new BigDecimal("0")) == 0){
			throw new BusinessException(fieldName+" 资金字段不能为0,请检查!");
		}
	}
	
	private static void checkAloneField(String mchId, String fieldName) {
		if(StringUtils.isBlank(mchId)){
			throw new BusinessException(fieldName+"字段不能为空,请检查!");
		}
	}
	
	/**
	 * 订单退款工作
	 */
	public static AltoResult orderRefund(AltoRefundMo refundMo,RestaurantPayCfg payCfg) throws Exception {
		refundMo.setNotify_url(refund_call_uri);
		verfiyRefund(refundMo);
		String cipher = DataEncrypt(JSONObject.toJSONString(refundMo), payCfg.getPrivateKey());
		Map<String,String> parmMap = new HashMap<String,String>();
		parmMap.put("sign_type","RSA");
		parmMap.put("sign",cipher);
		parmMap.put("data",JSONObject.toJSONString(refundMo));
		log.error(JSONObject.toJSONString(refundMo));
		String result = HttpUtil.doPost(refund_uri,parmMap);
		AltoResult data = JSONObject.parseObject(result,AltoResult.class);
		if(!result_code.equals(data.getCode()))
		{
			throw new BusinessException(data.getErr());
		}
		if(!data.Verify(data,payCfg.getPublicKey(),encode)){
			log.error("支付调用返回验证失败!");
		}
		data.setResult(JSONObject.parseObject(data.getData(),AltoRefundQryResult.class));
		return data;
	}
	
	private static void verfiyRefund(AltoRefundMo refundMo) {
		checkAloneField(refundMo.getMch_id(),"商户编号");
		checkTwoField(refundMo.getOut_refund_no(),"商户退款单号",refundMo.getTrade_no(),"交易订单号");
		checkAloneField(refundMo.getOut_trade_no(),"商户订单号");
		checkAloneNumField(new BigDecimal(refundMo.getAmount()),"支付金额");
		checkAloneNumField(new BigDecimal(refundMo.getRefund_amount()),"申请退款金额");
	}
	
	/**
	 * 支付查询
	 */
	public static AltoResult orderPayQry(AltoPayQryMo payQryMo,RestaurantPayCfg payCfg) throws Exception {
		verfiyPayQry(payQryMo);
		String cipher = DataEncrypt(JSONObject.toJSONString(payQryMo), payCfg.getPrivateKey());
		Map<String,String> parmMap = new HashMap<String,String>();
		parmMap.put("sign_type","RSA");
		parmMap.put("sign",cipher);
		parmMap.put("data",JSONObject.toJSONString(payQryMo));
		log.error(JSONObject.toJSONString(payQryMo));
		String result = HttpUtil.doPost(pay_qry_uri,parmMap);
		log.error(">>>>支付查询结果:"+result);
		AltoResult data = JSONObject.parseObject(result,AltoResult.class);
		if(!result_code.equals(data.getCode()))
		{
			throw new BusinessException(data.getErr());
		}
		if(!data.Verify(data,payCfg.getPublicKey(),encode)){
			log.error("支付调用返回验证失败!");
		}
		data.setResult(JSONObject.parseObject(data.getData(),AltoPayQryResult.class));
		return  data;
	}
	
	private static void verfiyPayQry(AltoPayQryMo payQryMo) {
		checkAloneField(payQryMo.getMch_id(),"商户编号");
		checkTwoField(payQryMo.getTrade_no(),"商户的订单号",payQryMo.getOut_trade_no(),"交易订单号");
	}
	
	private static void checkTwoField(String tradeNo, String msg1, String trade_no, String msg2) {
		if(StringUtils.isBlank(tradeNo) && StringUtils.isBlank(trade_no))
		{
			throw new BusinessException(msg1+"和"+msg2+"字段不能都为空,请检查!");
		}
	}
	
	/**
	 * 退款查询
	 */
	public static AltoResult orderRefundQry(AltoRefundQryMo refundQryMo,RestaurantPayCfg payCfg) throws Exception {
		verfiyRefundQry(refundQryMo);
		String cipher = DataEncrypt(JSONObject.toJSONString(refundQryMo), payCfg.getPrivateKey());
		Map<String,String> parmMap = new HashMap<String,String>();
		parmMap.put("sign_type","RSA");
		parmMap.put("sign",cipher);
		parmMap.put("data",JSONObject.toJSONString(refundQryMo));
		log.error(JSONObject.toJSONString(refundQryMo));
		String result = HttpUtil.doPost(refund_qry_uri,parmMap);
		log.error(">>>>退款查询结果:"+result);
		AltoResult data = JSONObject.parseObject(result,AltoResult.class);
		if(!result_code.equals(data.getCode()))
		{
			throw new BusinessException(data.getErr());
		}
		if(!data.Verify(data,payCfg.getPublicKey(),encode)){
			log.error("退款调用返回验证失败!");
			return  data;
		}
		JSONObject dtl = JSONObject.parseObject(data.getData());
		data.setResult(JSONObject.parseObject(data.getData(),AltoRefundQryResult.class));
		data.setDataDtl(dtl);
		return  data;
	}
	
	private static void verfiyRefundQry(AltoRefundQryMo refundQryMo) {
		checkAloneField(refundQryMo.getMch_id(),"商户编号");
		checkAloneField(refundQryMo.getOut_refund_no(),"商户退款单号");
		checkTwoField(refundQryMo.getTrade_no(),"商户的订单号",refundQryMo.getOut_trade_no(),"交易订单号");
	}
	
	/**
	 * 支付回调
	 */
	public static AltoPayCallResult orderPayCb(HttpServletRequest request, HttpServletResponse response,RestaurantPayCfg payCfg) throws IOException {
		ServletInputStream inputStream = request.getInputStream();
		ServletOutputStream outputStream = response.getOutputStream();
		String data = request.getParameter("data");
		String sign = request.getParameter("sign");
		AltoPayCallResult result =JSONObject.parseObject(data,AltoPayCallResult.class);
		if(! verfiyCallPay(data,sign,payCfg.getPublicKey()))
		{
			log.error("支付回调签名验证失败订单号:"+result.getOut_trade_no());
			response.setStatus(HttpStatus.SC_BAD_REQUEST);
			response.getOutputStream().write(("支付回调签名验证失败订单号:"+result.getTrade_no()).getBytes("UTF-8"));
			return null;
		}
		return result;
	}
	
	/**
	 * 校验签名
	 * @param data
	 * @param sign
	 * @return
	 */
	private static boolean verfiyCallPay(String data, String sign,String publicKey) {
		return Md5RsaUtils.verify(data,sign,publicKey,encode);
	}
	
	/**
	 * 退款回调
	 */
	public static AltoRefundCallResult orderRefundCb(HttpServletRequest request, HttpServletResponse response,RestaurantPayCfg payCfg) throws IOException {
		ServletInputStream inputStream = request.getInputStream();
		ServletOutputStream outputStream = response.getOutputStream();
		String data = request.getParameter("data");
		String sign = request.getParameter("sign");
		AltoRefundCallResult result = JSONObject.parseObject(data,AltoRefundCallResult.class);
		if(! verfiyCallPay(data,sign,payCfg.getPublicKey()))
		{
			log.error("退款回调签名验证失败订单号:"+result.getOut_trade_no());
			response.setStatus(HttpStatus.SC_BAD_REQUEST);
			response.getOutputStream().write(("退款回调签名验证失败订单号:"+result.getOut_trade_no()).getBytes("UTF-8"));
			return null;
		}
		return result;
	}
	
	public static void main(String [] ttt) throws Exception {


		final String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJvb3wm1Gt8wP0fY1sz9QCyVL7k6Nw/zF7jYY0anslunGoHp1WiFPK+sat2HOZQfly42nkYsbF7VxmLmCY9VLmTqL/L3I7lUt63X1KaXfjCzIYOOmW1xjwaoprYzZOEVUjGULF2Pc4Z5vIR6OuF4zl05CPElcP7QEhrRUC/lzCjxAgMBAAECgYB/Jt9M8h0cHCZkHPkQf0NNm+A1QtMNBgtCV/aV+9W8hBVSC0x5WslpoEYGuH025JbXsuNo6HD45XpV0MnXz2xqzcUXNJ5EYXgFSpX4OCm97kmTJRYw0Dzg4VMov7v4T0EBZbQXeGl2jaTJ0usZKzuQKzDJk2bB+Jd2w5xRLdtBqQJBAMzYxwtyL1BGtM30Z6Xa4KqVG/quzz0iA8TPh37560T9NfvYx9FuXkxRNUCM1P5iEiReAcxM6rbB2C5CDRB40UcCQQDCx3KVrsupz3eHBWDhmRgqc1PKTYL8u3Q5HcIu5z1aAJ0Qrq/kdFdh94HdlNMdhWBMRaJr/q1NPP8BO1T0RhAHAkAZ7jcEE+g5WTn5+D5GmHZoIYfxK7/AFVY0y7BzOl+10/fJcZ+Zu0bkkkMTcMBlkzSItf20RuhPSip7cJEGzMRxAkBNOca0khktupQpdHh0+b4bFp6iFxlYGvp5qtLSxdwNUzDy7E/QxE/hB8D1mYwaqEcF9pXvO4p6lTSFyIBmWWEBAkBobn+9vCbUgdvvkbV62ivqI0SRPk9yLnxZ5XVhfTXfslDfBPVJZgijmiybZylR/b06wbsn2SATalgqPXF5mCki";
		final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK3NXYvcA33nraQQj4ahu+cp7aoiLQTgu0oZv4gdeGD7YsHIQsyMVg3s/cZxMiJaoCJzE1CXpjZ9tLdZr9jM/Zz11zzu1fQTiRP6ZZv2enMCMA0CaaI5AcHJkZ5f+91DxMpAopuRCnftkgOdnNNsx3fm15nRWWMiY75VkW4eTrwwIDAQAB";
		String mchId = "100663";
		String amount = "1000";
		String subject = "骨香面餐厅消费";
		String out_trade_no = "order_201808221522";
		String out_refund_no = "refund_201808221522";
		String refundAmount = "1000";
		String tradeNo = "3221180822152277999";
		AltoResult result = null;
		
		RestaurantPayCfg cfg = new RestaurantPayCfg();
		cfg.setPublicKey(publicKey);
		cfg.setPrivateKey(privateKey);
		cfg.setMchId(mchId);
		
		
//		AltoPayMo payMo = new AltoPayMo();
//		payMo.setMch_id(mchId);
//		payMo.setOut_trade_no(out_trade_no);
//		payMo.setSubject(subject);
//		payMo.setAmount(amount);
//		payMo.setCurrency(currency);
//		payMo.setTrade_type(trade_type);
//		payMo.setNotify_url(pay_call_uri);
//		result = orderPay(payMo, cfg);
//		log.error(((AltoPayResult)result.getResult()).getUri());
//		log.error(((AltoPayResult)result.getResult()).getTrade_no());
		
		
		
//		AltoRefundMo refundMo = new AltoRefundMo();
//		refundMo.setMch_id(mchId);
//		refundMo.setOut_trade_no(out_trade_no);
//		refundMo.setTrade_no(tradeNo);
//		refundMo.setOut_refund_no(out_refund_no);
//		refundMo.setRefund_amount(refundAmount);
//		refundMo.setAmount(amount);
//		refundMo.setRefund_reason("店铺优惠免单");
//		refundMo.setNotify_url(refund_call_uri);
//		result = orderRefund(refundMo,cfg);

		
	
		AltoPayQryMo payQry = new AltoPayQryMo();
		payQry.setMch_id(mchId);
		payQry.setOut_trade_no(out_trade_no);
		payQry.setTrade_no(tradeNo);
		result = orderPayQry(payQry,cfg);
		AltoPayQryResult qry = (AltoPayQryResult) result.getResult();


		AltoRefundQryMo refundQry = new AltoRefundQryMo();
		refundQry.setMch_id(mchId);
		refundQry.setOut_trade_no(out_trade_no);
		refundQry.setTrade_no(tradeNo);
		refundQry.setOut_refund_no(out_refund_no);
		result = orderRefundQry(refundQry,cfg);
		AltoRefundQryResult refund = (AltoRefundQryResult) result.getResult();
		
		
		
	}
	
}
